
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Kafka的主从同步 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Kafka的主从同步 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">架构</div>
          <div class="card-question">在Kafka的整体架构中，ZooKeeper扮演了哪些核心的协调角色？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">架构</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">ZooKeeper在Kafka中用于分布式协调，主要负责管理集群的元数据、选举分区的Leader副本以及进行配置管理。每个Broker启动时会向ZooKeeper注册，并定期发送心跳。ZooKeeper通过记录Broker信息及各分区的Leader和Follower信息，来保障集群的高可用性和数据一致性。</div>
          </div>
          <div class="card-source">来源: Kafka的基本架构 -> 6. ZooKeeper</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">概念</div>
          <div class="card-question">请解释Kafka分区中主副本（Leader）和从副本（Follower）各自的职责以及它们之间的关系。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">概念</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主副本（Leader）是分区中唯一负责处理所有生产者写入和消费者读取请求的副本，它确保了数据操作的集中和一致性。从副本（Follower）的主要职责是从Leader同步数据，以保持与Leader的数据一致。Follower作为冗余备份，保证了数据的高可用性，当Leader发生故障时，Kafka会从同步的Follower中选举出新的Leader。</div>
          </div>
          <div class="card-source">来源: Kafka集群中的概念 -> 主副本（Leader） & 从副本（Follower）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">什么是Kafka的ISR（In-Sync Replicas）同步副本集？它如何在高可用性和数据一致性之间取得平衡？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">ISR是“同步副本集”的缩写，由Leader副本和所有与Leader完全同步的Follower副本组成。当生产者要求强持久化保证时（例如 acks=all），Kafka会确保消息被写入ISR中的所有副本后才向生产者确认成功。如果某个Follower长时间未能与Leader同步，它将被从ISR中移出。这种机制通过确保只有完全同步的副本参与确认和Leader选举，来平衡高可用性与数据一致性，从而在Leader故障时避免数据丢失。</div>
          </div>
          <div class="card-source">来源: Kafka集群中的概念 -> ISR（In-Sync Replicas）同步副本集</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">流程</div>
          <div class="card-question">简述一条消息从生产者发送到在Kafka集群中完成同步的完整数据写入流程。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">流程</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">数据写入流程分为五个步骤：1. 生产者将消息发送到指定分区的Leader副本。2. Leader副本接收消息并将其追加到本地日志文件。3. Leader将收到的消息传播给所有Follower副本。4. Follower副本成功写入消息后，向Leader发送确认（ACK）。5. Leader副本收到所有ISR中的Follower确认后，才向生产者发送最终的写入成功确认。</div>
          </div>
          <div class="card-source">来源: Kafka主从同步机制 -> 数据写入流程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">对比Kafka的同步复制（Synchronous Replication）和异步复制（Asynchronous Replication）在性能和数据一致性方面的优缺点。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">同步复制：优点是数据一致性强，能保证数据不丢失；缺点是性能开销大，需要等待所有同步副本确认，导致写入延迟较高。<br>异步复制：优点是性能开销小，写入延迟低，可用性高；缺点是数据一致性弱，在Leader副本故障时，部分未同步到Follower的消息可能会丢失。</div>
          </div>
          <div class="card-source">来源: kafka同步方式 -> 1. 同步复制（Synchronous Replication） & 2. 异步复制（Asynchronous Replication）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">解释Kafka生产者配置中的`acks`参数三个不同值（0, 1, all/-1）的含义及其在性能和数据可靠性上的权衡。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">acks=0：生产者不等待任何确认，性能最高，但数据可能会丢失。<br>acks=1：生产者等待Leader副本的确认，可以保证数据至少被写入Leader，但如果Leader在同步数据到Follower前失败，数据可能会丢失。<br>acks=-1 (或 all)：生产者等待所有ISR（同步副本集）中的副本确认，提供了最高的一致性保证和数据可靠性，但写入延迟也最高。</div>
          </div>
          <div class="card-source">来源: 数据一致性保证 -> 2. 数据确认机制（Acknowledgements）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">当一个分区的Leader副本发生故障时，Kafka是如何进行故障恢复以保证服务的可用性？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">当Leader副本故障时，Kafka通过ZooKeeper触发Leader选举过程。它会从该分区的ISR（In-Sync Replicas）集合中选择一个与原Leader数据最同步的Follower副本作为新的Leader。这个过程确保了新当选的Leader拥有最新的数据，从而快速恢复服务，保证了数据的可用性和最小的数据丢失。</div>
          </div>
          <div class="card-source">来源: 故障恢复 -> 1. 副本机制（Replication） & 2. Leader 选举</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">概念</div>
          <div class="card-question">什么是Kafka的消费者组（Consumer Group），它的主要作用是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">概念</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">消费者组是Kafka用来实现消息消费负载均衡和高可用性的概念。同一个消费者组中的多个消费者共同消费一个或多个主题的消息，但每个分区的消息只能被该组内的一个消费者实例消费。这样，Kafka可以将不同分区分配给组内的不同消费者，从而实现并行处理和负载均衡。</div>
          </div>
          <div class="card-source">来源: Kafka的基本架构 -> 5. 消费者（Consumer）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">Kafka从0.11版本引入的事务支持是如何增强数据一致性的？请说明其包含的两个关键特性。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">Kafka的事务支持允许生产者将一系列写操作作为一个原子操作提交，从而实现了跨分区和跨主题的一致性保证。其关键特性包括：<br>1. 幂等生产者（Idempotent Producer）：通过为每个消息分配唯一序列号，在Broker端进行去重，保证生产者重试写操作不会导致重复消息。<br>2. 事务性生产者（Transactional Producer）：允许多个写操作在一个事务中提交，保证这些操作要么全部成功，要么全部失败。</div>
          </div>
          <div class="card-source">来源: 数据一致性保证 -> 4. 事务支持（Transactions）</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
